<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { ElImage, ElImageViewer } from 'element-plus'

interface ImageItem {
  id: number
  title: string
  description: string
  tags: string[]
  url: string
  placeholder: string
  aspectRatio: number
}

const props = defineProps({
  items: { type: Array as () => ImageItem[], default: () => [] },
  isLoading: { type: Boolean, default: false },
  isComplete: { type: Boolean, default: false }
})

// 响应式数据
const columns = ref(4)
const columnItems = ref<ImageItem[][]>([])
const waterfallElement = ref<HTMLElement | null>(null)
const columnWidth = ref(0)
const previewVisible = ref(false)
const previewIndex = ref(0)

// 预览图片列表
const previewList = computed(() => props.items.map(item => item.url))

// 更新列宽
const updateColumnWidth = () => {
  if (waterfallElement.value) {
    const containerWidth = waterfallElement.value.clientWidth
    const gap = 18 // 必须与CSS中的gap保持一致
    const totalGap = (columns.value - 1) * gap
    columnWidth.value = (containerWidth - totalGap) / columns.value
  }
}

// 计算瀑布流布局
const calculateLayout = () => {
  const cols: ImageItem[][] = Array(columns.value).fill(null).map(() => [])
  const colHeights = Array(columns.value).fill(0)

  props.items.forEach(item => {
    const itemHeight = columnWidth.value * item.aspectRatio
    const minHeight = Math.min(...colHeights)
    const colIndex = colHeights.indexOf(minHeight)
    cols[colIndex].push(item)
    colHeights[colIndex] += itemHeight
  })

  return cols
}

const refreshLayout = () => {
  updateColumnWidth()
  if (columnWidth.value > 0) {
    columnItems.value = calculateLayout()
  }
}

// 响应式调整
const handleResize = () => {
  const width = window.innerWidth
  // 调整列数逻辑
  if (width < 480) {
    columns.value = 1
  } else if (width < 768) {
    columns.value = 2
  } else if (width < 1024) {
    columns.value = 3
  } else {
    columns.value = 4
  }
  refreshLayout()
}

// 打开预览 - 修复索引问题
const openPreview = (index: number) => {
  previewIndex.value = index
  previewVisible.value = true
}

onMounted(() => {
  window.addEventListener('resize', handleResize)
  handleResize() // 初始调整
  nextTick(refreshLayout) // 初始化布局
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
})

watch(() => props.items, () => {
  nextTick(refreshLayout) // 数据变化时更新布局
}, { deep: true })
</script>

<template>
  <div class="waterfall-container">
    <div class="image-counter">
      已加载: {{ items.length }} 张图片
      <div v-if="isComplete" class="no-more">
        <i class="fas fa-check-circle"></i> 已加载全部图片
      </div>
    </div>

    <div class="waterfall" :style="{ '--columns': columns }" ref="waterfallElement">
      <div
        v-for="(column, index) in columnItems"
        :key="index"
        class="waterfall-column"
      >
        <div
          v-for="item in column"
          :key="item.id"
          class="waterfall-item"
          @click="openPreview(items.findIndex(i => i.id === item.id))"
        >
          <el-image
            :src="item.url"
            :alt="item.title"
            class="item-img"
            fit="cover"
            hide-on-click-modal
          >
            <template #placeholder>
              <div class="image-placeholder">
                <div class="loader-spinner small"></div>
              </div>
            </template>
            <template #error>
              <div class="image-error">
                <i class="el-icon-picture-outline"></i>
                <span>加载失败</span>
              </div>
            </template>
          </el-image>
          <div class="item-content">
            <h3 class="item-title">{{ item.title }}</h3>
          </div>
        </div>
      </div>
    </div>

    <div v-if="isLoading" class="loader">
      <div class="loader-spinner"></div>
      <div class="loader-text">正在加载更多图片...</div>
    </div>

    <div v-else-if="items.length === 0" class="no-images">
      <i class="el-icon-picture-outline"></i>
      <p>暂无图片</p>
    </div>

    <!-- 独立预览组件 -->
    <el-image-viewer
      v-if="previewVisible"
      :url-list="previewList"
      :initial-index="previewIndex"
      @close="previewVisible = false"
    />
  </div>
</template>

<style scoped>
.waterfall-container {
  margin: 0 auto;
  position: relative;
  max-width: 1600px;
}

.image-counter {
  text-align: center;
  margin-bottom: 20px;
  color: #a0aec0;
  font-size: 1.1rem;
  font-weight: 500;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.no-more {
  padding: 8px 15px;
  color: #a0aec0;
  font-size: 0.95rem;
  font-weight: 500;
  background: rgba(255, 255, 255, 0.03);
  border-radius: 12px;
}

.waterfall {
  display: grid;
  grid-template-columns: repeat(var(--columns), 1fr);
  gap: 18px;
  margin-bottom: 30px;
}

.waterfall-column {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.waterfall-item {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.25);
  transition: all 0.35s ease;
  cursor: pointer;
}

.waterfall-item:hover {
  transform: translateY(-5px);
  box-shadow: 0 12px 25px rgba(0, 0, 0, 0.35);
  background: rgba(255, 255, 255, 0.08);
}

.item-img {
  width: 100%;
  display: block;
  transition: transform 0.45s ease;
  background: linear-gradient(45deg, #2d3748, #1a202c);
  min-height: 200px;
  max-height: 320px;
  object-fit: cover;
}

.waterfall-item:hover .item-img {
  transform: scale(1.03);
}

.item-content {
  padding: 16px;
}

.item-title {
  font-size: 1.15rem;
  margin-bottom: 8px;
  color: #e2e8f0;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.loader {
  text-align: center;
  padding: 25px;
  margin: 20px 0;
}

.loader-spinner {
  display: inline-block;
  width: 45px;
  height: 45px;
  border: 4px solid rgba(106, 17, 203, 0.3);
  border-radius: 50%;
  border-top-color: #6a11cb;
  animation: spin 1s linear infinite;
  margin-bottom: 15px;
}

.loader-spinner.small {
  width: 30px;
  height: 30px;
  border-width: 3px;
}

.image-placeholder, .image-error {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 200px;
  background: rgba(45, 55, 72, 0.3);
  color: #a0aec0;
}

.image-error {
  flex-direction: column;
  font-size: 14px;
}

.image-error i {
  font-size: 40px;
  margin-bottom: 10px;
}

.no-images {
  text-align: center;
  padding: 50px 20px;
  color: #a0aec0;
  font-size: 1.2rem;
}

.no-images i {
  font-size: 60px;
  margin-bottom: 20px;
  display: block;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 1200px) {
  .waterfall {
    --columns: 3 !important;
  }
}

@media (max-width: 1024px) {
  .waterfall {
    --columns: 3 !important;
  }
}

@media (max-width: 768px) {
  .waterfall {
    --columns: 2 !important;
  }
}

@media (max-width: 480px) {
  .waterfall {
    --columns: 1 !important;
  }

  .item-img {
    min-height: 180px;
  }
}

/* 修复预览样式 */
:global(.el-image-viewer) {
  background-color: rgba(0, 0, 0, 0.85) !important;
}

:global(.el-image-viewer__wrapper) {
  .el-image-viewer__mask {
    opacity: 0.9 !important;
  }

  .el-image-viewer__canvas {
    img {
      max-width: 90vw;
      max-height: 90vh;
      object-fit: contain;
    }
  }

  .el-image-viewer__btn {
    color: #fff;
    background: rgba(0, 0, 0, 0.3);
    border-radius: 50%;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.3s;

    &:hover {
      background: rgba(0, 0, 0, 0.5);
    }

    i {
      font-size: 24px;
    }
  }
}
</style>
